/* eslint-disable no-template-curly-in-string */
import { useDeepCompareEffect, useDynamicList } from 'ahooks';
import { Button, Dropdown, Empty, Icon, Input, Menu, Modal, Tooltip } from 'antd';
import React, { useState } from 'react';
import { omit } from 'lodash';
import {
  STRING_TYPE,
  OBJECT_TYPE,
  ARRAY_TYPE,
  RULES,
  RULE_TYPES as _RULE_TYPES,
} from '../settings';
import NotEmpty from './NotEmpty';
import Required from './Required';
import Length from './Length';
import Range from './Range';
import Enums from './Enums';
import Regex from './Regex';
import Formatter from './Formatter';
import Custom from './Custom';
import styles from '../styles.less';
import NotBlank from './NotBlank';
import useModal from '@/hooks/UseModal';

export function getRuleConfigs(rules) {
  if (rules.length === 0) {
    return [];
  }
  return rules[0].config;
}

const RuleComponentMap = {
  [RULES.required.type]: <Required />,
  [RULES.not_empty.type]: <NotEmpty />,
  [RULES.length.type]: <Length />,
  [RULES.range.type]: <Range />,
  [RULES.enums.type]: <Enums />,
  [RULES.regex.type]: <Regex />,
  [RULES.formatter.type]: <Formatter />,
  [RULES.custom.type]: <Custom />,
  [RULES.not_blank.type]: <NotBlank />,
};

function renderPlaceHolder(node, item) {
  if (item.type === RULES.required.type) {
    return '不存在或为null';
  }
  if (item.type === RULES.not_empty.type) {
    if (node.nodeType === ARRAY_TYPE) {
      return '不能为空数组';
    }
    if (node.nodeType === OBJECT_TYPE) {
      return '不能为空对象';
    }
    if (node.nodeType === STRING_TYPE) {
      return '不能为空字符串';
    }
  }
  if (item.type === RULES.length.type) {
    return '长度必须大于(等于)最小值，同时长度必须小于(等于)最大值';
  }
  if (item.type === RULES.range.type) {
    return '必须大于(等于)最小值，同时必须小于(等于)最大值';
  }
  if (item.type === RULES.enums.type) {
    return `必须在枚举值[${item.enums}]之中`;
  }
  if (item.type === RULES.regex.type) {
    return `不满足正则表达式: ${item.pattern}`;
  }
  if (item.type === RULES.formatter.type) {
    if (item.format === 'DATE') {
      return `不满足日期格式[${item.dateFormat}]`;
    }
    if (item.format === 'PRICE') {
      return '不满足价格格式';
    }
    if (item.format === 'INTEGER') {
      return '不满足整数格式';
    }
    if (item.format === 'EMAIL') {
      return '不满足邮箱格式';
    }
    if (item.format === 'PHONE') {
      return '不满足手机/电话格式';
    }
    return '';
  }
  if (item.type === RULES.custom.type) {
    return '以实际抛出异常为准';
  }
  if (item.type === RULES.not_blank.type) {
    return '不能为空白字符串';
  }
  throw new Error('renderPlaceHolder');
}

function CustomErrorMessageButton({ node, item, onOk }) {
  const { visible, showModal, hideModal } = useModal();
  const [value, setValue] = useState(item.errorTemplate);
  return (
    <>
      <Tooltip title="自定义errorMessage">
        <Icon type="edit" className={styles.edit} onClick={showModal} />
      </Tooltip>
      <Modal
        title="自定义errorMessage"
        visible={visible}
        onCancel={hideModal}
        onOk={() => {
          onOk(value);
          hideModal();
        }}
      >
        <Input
          style={{ marginBottom: 16 }}
          placeholder={renderPlaceHolder(node, item)}
          value={value}
          onChange={e => setValue(e.target.value)}
        />
      </Modal>
    </>
  );
}

function BasicForString({ node, value = [], onChange, filter = () => true }) {
  const { list, remove, getKey, push, replace } = useDynamicList(value);
  const addRule = type => push({ type });
  const allTypes = value.map(item => item.type);

  const RULE_TYPES = _RULE_TYPES.filter(filter);

  const [ruleTypes, setRuleTypes] = useState(
    RULE_TYPES.filter(each => !allTypes.includes(each.value))
  );

  useDeepCompareEffect(() => {
    onChange(list);
  }, [list]);

  const menu = (
    <Menu
      onClick={e => {
        addRule(e.key);
        if (e.key !== RULES.custom.type) {
          setRuleTypes(ruleTypes.filter(item => item.value !== e.key));
        }
      }}
    >
      {ruleTypes.map(k => (
        <Menu.Item key={k.value}>{k.title}</Menu.Item>
      ))}
    </Menu>
  );

  if (list.length === 0) {
    return (
      <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无规则">
        <Dropdown overlay={menu} placement="topCenter">
          <Button icon="plus" type="link">
            添加规则
          </Button>
        </Dropdown>
      </Empty>
    );
  }

  const renderRule = (item, index) => {
    const Component = RuleComponentMap[item.type];
    const value = omit(item, 'type');
    const onChange = value => replace(index, { type: item.type, ...value });
    return React.cloneElement(Component, { value, onChange });
  };

  return (
    <>
      {list.map((item, index) => (
        <div
          className={styles.flex}
          style={{
            background: '#fff',
            borderBottom: '1px solid #e8e8e8',
            borderLeft: '1px solid #e8e8e8',
            borderRight: '1px solid #e8e8e8',
            borderTop: index === 0 ? '1px solid #e8e8e8' : 'none',
            borderTopLeftRadius: index === 0 ? '4px' : '0px',
            borderTopRightRadius: index === 0 ? '4px' : '0px',
            borderBottomLeftRadius: index === list.length - 1 ? '4px' : '0px',
            borderBottomRightRadius: index === list.length - 1 ? '4px' : '0px',
          }}
          key={getKey(index)}
        >
          <Tooltip title="移除规则">
            <Icon
              className={styles.action}
              onClick={() => {
                const originIndex = RULE_TYPES.findIndex(each => each.value === item.type);

                if (ruleTypes.length === 0) {
                  setRuleTypes([RULE_TYPES[originIndex]]);
                } else {
                  const firstIndex = RULE_TYPES.findIndex(
                    each => each.value === ruleTypes[0].value
                  );
                  const lastIndex = RULE_TYPES.findIndex(
                    each => each.value === ruleTypes[ruleTypes.length - 1].value
                  );
                  if (originIndex < firstIndex) {
                    setRuleTypes([RULE_TYPES[originIndex], ...ruleTypes]);
                  } else if (originIndex > lastIndex) {
                    setRuleTypes([...ruleTypes, RULE_TYPES[originIndex]]);
                  }

                  for (let i = 0; i < ruleTypes.length - 1; i++) {
                    const front = ruleTypes[i];
                    const next = ruleTypes[i + 1];
                    const frontIndex = RULE_TYPES.findIndex(each => each.value === front.value);
                    const nextIndex = RULE_TYPES.findIndex(each => each.value === next.value);
                    if (originIndex > frontIndex && originIndex < nextIndex) {
                      setRuleTypes([
                        ...ruleTypes.slice(0, i + 1),
                        RULE_TYPES[originIndex],
                        ...ruleTypes.slice(i + 1),
                      ]);
                    }
                  }
                }

                remove(index);
              }}
              type="delete"
            />
          </Tooltip>

          {renderRule(item, index)}
          <CustomErrorMessageButton
            node={node}
            item={item}
            onOk={errorTemplate => replace(index, { ...item, errorTemplate })}
          />
        </div>
      ))}
      {ruleTypes.length > 0 && (
        <Dropdown className="margin-top" overlay={menu} placement="topCenter">
          <Button icon="plus" type="dashed" block>
            添加规则
          </Button>
        </Dropdown>
      )}
    </>
  );
}

export default BasicForString;
